package audio;
import common.ConstVars;
import org.apache.commons.math.complex.Complex;
import org.apache.commons.math.transform.FastFourierTransformer;

import javax.sound.sampled.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.util.ArrayList;

public class AudioCapture01 extends JFrame{

        boolean c4 = false;
        boolean stopCapture = false;
        ByteArrayOutputStream
        byteArrayOutputStream;
        AudioFormat audioFormat;
        TargetDataLine targetDataLine;
        AudioInputStream audioInputStream;
        SourceDataLine sourceDataLine;
        String speakerName= "", speakerWord = "";
        String filename = "";
        final JButton captureBtn = new JButton("Capture");
        double[] currWordVector = null;
        public boolean INVISIBLE = false;

        public static void main(String args[]){
                new AudioCapture01(args[0]);
        }//end main

        public void startRecording()
        {
                captureBtn.getActionListeners()[0].actionPerformed(null);
        }

        public double[] getCurrVector()
        {
                double[] retval = currWordVector;
        if(currWordVector != null)
            currWordVector = null;
                return retval;
        }


        public AudioCapture01(String filename){//constructor
                this.filename = filename;

                final JButton stopBtn = new JButton("Stop");
                final JButton playBtn = new JButton("Playback");

                ///////////////////////////////////////////////////////
                //GUI portion borrowed from Michael's image code     //   
                ///////////////////////////////////////////////////////

                Button alex, michael, kevin, aaron, other;
                Button forward, backward, stop, left, right, wother, speed, slow;

                alex = new Button(ConstVars.ALEX);
                michael = new Button(ConstVars.MICHAEL);
                kevin = new Button(ConstVars.KEVIN);
                aaron = new Button(ConstVars.AARON);
                other = new Button(ConstVars.OTHER);
                forward = new Button("forward");
                backward = new Button("backward");
                stop = new Button("stop");
                left = new Button("left");
                speed = new Button("speed");
                slow = new Button("slow");
                right = new Button("right");
                wother = new Button("wother");

                ButtonListener b = new ButtonListener();

                alex.addActionListener(b);
                michael.addActionListener(b);
                kevin.addActionListener(b);
                aaron.addActionListener(b);
                other.addActionListener(b);
                //save.addActionListener(b);
                forward.addActionListener(b);
                backward.addActionListener(b);
                stop.addActionListener(b);
                left.addActionListener(b);
                speed.addActionListener(b);
                slow.addActionListener(b);
                right.addActionListener(b);
                wother.addActionListener(b);

                getContentPane().add(alex);
                getContentPane().add(michael);
                getContentPane().add(kevin);
                getContentPane().add(aaron);
                getContentPane().add(other);
                getContentPane().add(forward);
                getContentPane().add(backward);
                getContentPane().add(stop);
                getContentPane().add(left);
                getContentPane().add(right);
                getContentPane().add(speed);
                getContentPane().add(slow);
                getContentPane().add(wother);
                //////////////////////////////////////////////////////
                // End borrowed code                                //
                //////////////////////////////////////////////////////

                captureBtn.setEnabled(true);
                stopBtn.setEnabled(false);
                playBtn.setEnabled(false);

                //Register anonymous listeners
                captureBtn.addActionListener( new ActionListener(){
                        public void actionPerformed(ActionEvent e){
                                captureBtn.setEnabled(false);
                                stopBtn.setEnabled(true);
                                playBtn.setEnabled(false);
                                //Capture input data from the microphone until the Stop button is clicked.
                                captureAudio();
                        }//end actionPerformed
                }//end ActionListener
                                );//end addActionListener()
                getContentPane().add(captureBtn);

                stopBtn.addActionListener(
                                new ActionListener(){
                                        public void actionPerformed(ActionEvent e){
                                                captureBtn.setEnabled(true);
                                                stopBtn.setEnabled(false);
                                                playBtn.setEnabled(true);
                                                //Terminate the capturing of input data from the microphone.
                                                stopCapture = true;
                                        }//end actionPerformed
                                }//end ActionListener
                                );//end addActionListener()
                getContentPane().add(stopBtn);

                playBtn.addActionListener(
                                new ActionListener(){
                                        public void actionPerformed(ActionEvent e){
                                                //Play back all of the data that was saved during capture.
                                                playAudio();
                                        }//end actionPerformed
                                }//end ActionListener
                                );//end addActionListener()
                getContentPane().add(playBtn);

                getContentPane().setLayout(new FlowLayout());
                setTitle("Capture/Playback Demo");
                setDefaultCloseOperation(EXIT_ON_CLOSE);
                setSize(430,200);
                setVisible(true);
        }//end constructor

        //This method captures audio input from a microphone and saves it in a ByteArrayOutputStream object.
        private void captureAudio(){
                try{
                        //Get everything set up for capture
                        audioFormat = getAudioFormat();
                        DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class,audioFormat);
                        targetDataLine = (TargetDataLine)AudioSystem.getLine(dataLineInfo);
                        targetDataLine.open(audioFormat);
                        targetDataLine.start();

                        //Create a thread to capture the microphone data and start it running.  
                        //It will run until the Stop button is clicked.
                        Thread captureThread = new Thread(new CaptureThread());
                        captureThread.start();
                } catch (Exception e) {
                        e.printStackTrace();
                        System.exit(0);
                }
        }

        //This method plays back the audio data that has been saved in the ByteArrayOutputStream
        private void playAudio() {
                try{
                        //Get everything set up for playback.
                        //Get the previously-saved data into a byte array object.
                        byte audioData[] = byteArrayOutputStream.toByteArray();

                        //Get an input stream on the byte array containing the data
                        InputStream byteArrayInputStream = new ByteArrayInputStream(audioData);
                        AudioFormat audioFormat = getAudioFormat();
                        audioInputStream = new AudioInputStream(byteArrayInputStream, audioFormat, audioData.length/audioFormat.getFrameSize());
                        DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class,audioFormat);
                        sourceDataLine = (SourceDataLine)AudioSystem.getLine(dataLineInfo);
                        sourceDataLine.open(audioFormat);
                        sourceDataLine.start();

                        //Create a thread to play back the data and start it running.
                        //It will run until all the data has been played back.
                        Thread playThread = new Thread(new PlayThread());
                        playThread.start();
                } catch (Exception e) {
                        e.printStackTrace();
                        System.exit(0);
                }//end catch
        }//end playAudio

        //This method creates and returns an AudioFormat object for a given set of format parameters.   
        //If these parameters don't work well for you, try some of the other allowable parameter values,
        //which are shown in comments following the declarations.
        private AudioFormat getAudioFormat(){
                float sampleRate = 8000.0F;
                //8000,11025,16000,22050,44100
                int sampleSizeInBits = 16;
                //8,16
                int channels = 1;
                //1,2
                boolean signed = true;
                //true,false
                boolean bigEndian = false;
                //true,false
                return new AudioFormat(
                                sampleRate,
                                sampleSizeInBits,
                                channels,
                                signed,
                                bigEndian);
        }//end getAudioFormat
        //===================================//

        private static void decode(byte[] input, double[] output){

                assert input.length == 2*output.length;
                for(int i = 0; i < output.length; i++){
                        output[i] = (short)(((0xFF & input[2*i+1]) << 8) | (0xFF & input[2*i]));
                        output[i] /= Short.MAX_VALUE;
                }
        }

        class CaptureThread extends Thread{
                final int W = 4096;
                byte tempBuffer[] = new byte[W*getAudioFormat().getSampleSizeInBits()/8];
                double[] inbuf = new double[W];
                double[] fftbuf = new double[W/2];
                FastFourierTransformer transformer = new FastFourierTransformer();

                final int bucketsize = 1000;
                final double threshold = 0.02;
                final double endthreshold = 0.04;
                
                final double flow = 0;
                final double fhigh = 4000;
                final int M = 20;

                public double fmel ( double f ){
                        return ( 1127 * Math.log( 1 + f/700 ) ) ; 
                }
                
                public double ifmel ( double f ) {
                        return ( 700 * ( Math.exp( f/1127 ) - 1 ) ) ;
                }
                
                public double fb( int i ){
                        return ( (256/2)/8000.0 ) * ifmel ( fmel( flow ) + i*( (fmel(fhigh)-fmel(flow))/(M+1) ) ) ;///256 for fft sized input
                }
                
                private double H ( int i, int k ) {
                        if ( k < fb(i-1) ) 
                                return 0;
                        else if ( ( fb(i-1) <= k ) && ( k <= fb(i) ) ) 
                                return ( k - fb(i-1) ) / ( fb(i) - fb(i-1) ) ;
                        else if ( ( fb(i) <= k ) && ( k <= fb(i+1) ) )
                                return ( fb(i+1) - k ) / ( fb(i+1) - fb(i) ) ;
                        else
                                return 0;       
                }

        private void calcDelta( double[] data, int start, int end, int offset, int calcstart )
        {
            assert data.length >= calcstart + (end - start) / offset;
            for( int l = start; l< end; l+= offset)
            {
                double c1  = l+1*offset  < end   ? data[l+1*offset] : data[end-1*offset]; 
                double c_1 = l-1*offset  > start ? data[l-1*offset] : data[start];
                double c2  = l+2*offset  < end   ? data[l+2*offset] : data[end-1*offset];
                double c_2 = l-2*offset  > start ? data[l-2*offset] : data[start];
                data[calcstart + (l-start)/offset] =  ( (c1-c_1) + 2*(c2-c_2) ) / 10 ; 
            }
        }


                
                public void run(){
                        stopCapture = false;
                        int sampleframe = 1;
                        long sampleindex = 1;
                        boolean inWord = false;
                        int midWordIndex = 0;
                        double[] word2FFT = new double[W];

                        try{
                                BufferedWriter out = new BufferedWriter(new FileWriter(filename, true));

                                int silence = 0;
                                int speech = 0;
                                boolean isspeech = false;

                                int wordstart = 0;
                                int startbuf = 0;
                                int wordend = 0;
                                int endbuf = 0;
                                ArrayList<Double> wordbuf = new ArrayList<Double>();

                                double count = 0;
                                double count2 = 0;
                                while(!stopCapture){
                                        int numbytesread = 0; int tmp = 0;
                                        while(numbytesread < tempBuffer.length){
                                                if ((tmp = targetDataLine.read(tempBuffer, 0, tempBuffer.length)) < 0) break;
                                                else numbytesread+=tmp;
                    }
                                        decode(tempBuffer,inbuf);
                                        System.out.println("\t\t\t"+sampleframe++);

                                        /*
                                        for(int i = 0; i < inbuf.length; i++){
                                                out2.write( (count+=1) + " " + inbuf[i] + "\n");
                                        }
                                        */

                                        int framesize = 128; // 16ms worth of samples
                                        int numframes = inbuf.length/framesize; // 32 when framesize = 128
                                        double[] stebuf = new double[numframes];
                                        for( int f = 0; f < numframes; f++){
                                                double ste = 0;
                                                for( int i = f*framesize; i < (f+1)*framesize; i++ ){
                                                        ste += inbuf[i]*inbuf[i];
                                                }
                                                ste /= framesize;
                                                stebuf[f] = ste;

                                                //out3.write( (((f+1)*framesize)+(4096*(sampleframe-2))) + " " + ste + "\n" );
                                        }       

                                        for( int i = 0; i < numframes; i++){
                                                if ( !isspeech ) 
                                                        if ( stebuf[i] >= threshold){
                                                                speech++;
                                                                isspeech = ((speech%=5) == 0); // set isspeech = true if needed

                                                                if ( isspeech ) { // realized starting of word
                                                                        wordstart = i; startbuf = sampleframe; 
                                                                }

                                                                for(int k = i*framesize; k < (i+1)*framesize; k++)
                                                                        wordbuf.add(inbuf[k]);          
                                                        }
                                                        else {
                                                                speech = 0;
                                                                wordbuf.clear();
                                                        }
                                                else
                                                        if ( stebuf[i] < threshold ) {
                                                                silence++;
                                                                isspeech = ((silence%=10) != 0); // set isspeech = false if needed
                                                                if ( ! isspeech ) { // end of word
                                                                        wordend = i;
                                                                        endbuf = sampleframe; 
                                                                        System.out.println(startbuf + " " + wordstart + "\t" + endbuf + " " + wordend);

                                                                        double[] wordbufarray = new double[W];
                                                                        if ( wordbuf.size()-(9*framesize) <= W)
                                                                                for(int k = 0; k < wordbuf.size()-(9*framesize); k++)
                                                                                        wordbufarray[k] = wordbuf.get(k);
                                                                        else
                                                                                for(int k = 0; k < W; k++)
                                                                                        wordbufarray[k] = wordbuf.get(k);
                                                                        //wordbufarray now contains the signal for a word
                                                                        

                                                                        
                                                                        int frameadvance = 2; // advance factor = 1/frameadvance
                                                                        int frameblocksize = 256;
                                                                        int numframeblocks = wordbufarray.length / (frameblocksize/frameadvance) + 1 - frameadvance;
                                                                        int numfbins = frameblocksize/2;
                                                                        int numcoeffs = 12;
                                                                        
                                                                        double[] fout = new double[numframeblocks*numcoeffs*3+ numframeblocks*3]; // *3 because adding 12 delta coefficients and 12 delta-delta
                                                                                                              //per frame; +numframeblocks*3 because adding energy per frame
                                                                                                              //delta energy, and delta-delta energy
                                                                        for(int l = 0; l < numframeblocks; l++)
                                                                        {
                                                                                double[] frameblock = new double[frameblocksize];
                                                                                for ( int j = 0; j < frameblocksize; j++ ) {
                                                                                        frameblock[j] = wordbufarray[(frameblocksize/frameadvance)*l + j] * (0.54-0.46*Math.cos((2*Math.PI*j)/(frameblocksize-1)));
                                                                                }
                                                                                // frameblock now contains a windowed frame of signal
                                                                                Complex[] fftbuf = (new FastFourierTransformer()).transform(frameblock);
                                                                                double[] powspect = new double[fftbuf.length/2];
                                                                                for (int j = 0; j < fftbuf.length/2; j++) {
                                                                                        powspect[j] = Math.abs(fftbuf[j].multiply( fftbuf[j].conjugate() ).getReal());
                                                                                }
                                                                                // powspect now contains the magnitude spectrum of the window of signal
                                                                                double[] logenergy = new double[M];
                                                                                for ( int ith = 1 ; ith <= M; ith++ ) {
                                                                                        for ( int k = 0; k < fftbuf.length/2; k++ ){
                                                                                                logenergy[ith-1] += powspect[k] * H( ith, k ); 
                                                                                        }
                                                                                        if ( logenergy[ith-1] != 0){
                                                                                                logenergy[ith-1] = Math.log10(logenergy[ith-1]);
                                                                                        }
                                                                                }
                                                                                // logenergy now contains the log energy outputs of the filter bank
                                        
                                                                                double[] mfcc = new double[numcoeffs+1]; 
                                                                                for ( int j = 1; j <= mfcc.length; j++ ) {
                                                                                        for ( int k = 1; k <= M; k++) {
                                                                                                mfcc[j-1] += logenergy[k-1] * Math.cos( j*( k - (1/2) ) * ( Math.PI / M) ) ;
                                                                                        }
                                                                                }
                                                                                // mfcc now contains the coefficients 
                                                                                for ( int j = 1; j < mfcc.length; j++ ) { // discard first coefficient since proportional to log energy => function of distance to microphone, vocal effort, etc.
                                                                                        fout[l*numcoeffs + (j-1)] = mfcc[j];
                                                                                }
                                                                                // fout now has the mfccs for this frame appended to the end
                                                                        }
                                                                        
                                                                        // calculate delta mfccs
                                    /*
                                                                        for ( int l = 0; l < numframeblocks; l++ ) {
                                                                                for ( int k = 0; k < numcoeffs; k++ ) {
                                                                                        double c1 = (l*numcoeffs + k+1) < (numframeblocks*numcoeffs) ? fout[l*numcoeffs + k+1] : 0;
                                                                                        double c_1 = (l*numcoeffs + k-1) >= 0 ? fout[l*numcoeffs + k-1] : 0;
                                                                                        double c2 = (l*numcoeffs + k+2) < (numframeblocks*numcoeffs) ? fout[l*numcoeffs + k+2] : 0;
                                                                                        double c_2 = (l*numcoeffs + k-2) >= 0 ? fout[l*numcoeffs + k-2] : 0;
                                                                                        
                                                                                        fout[numframeblocks*numcoeffs + l*numcoeffs + k] = ( (c1-c_1) + 2*(c2-c_2) ) / 10 ; 
                                                                                }
                                                                        }
                                    int top = numframeblocks*numcoeffs;
                                    for( int k = 0; k < numcoeffs; k++)
                                    {
                                        for( int l = 0; l < numframeblocks; l++)
                                        {
                                                                                        double c1  =  l*numcoeffs+k+1*numcoeffs < top ? fout[ l*numcoeffs+k+1*numcoeffs ] : fout[ (numframeblocks-1)*numcoeffs + k ];
                                                                                        double c_1 =  l*numcoeffs+k-1*numcoeffs >= 0  ? fout[ l*numcoeffs+k-1*numcoeffs ] : fout[k];
                                                                                        double c2  =  l*numcoeffs+k+2*numcoeffs < top ? fout[ l*numcoeffs+k+2*numcoeffs ] : fout[ (numframeblocks-1)*numcoeffs + k ];
                                                                                        double c_2 =  l*numcoeffs+k-2*numcoeffs >= 0  ? fout[ l*numcoeffs+k-2*numcoeffs ] : fout[k];
                                                                                        
                                                                                        fout[numframeblocks*numcoeffs + l*numcoeffs + k] = ( (c1-c_1) + 2*(c2-c_2) ) / 10 ; 
                                                                                }
                                                                        }



                                                                        
                                                                        // calculate delta-delta mfccs
                                    //TODO change out-of-bounds value equal to endpoint values, NOT to 0
                                    int begin = top;
                                    /*
                                                                        for ( int l = 0; l < numframeblocks; l++ ) {
                                                                                for ( int k = 0; k < numcoeffs; k++ ) {
                                                                                        double c1 = (numframeblocks*numcoeffs + l*numcoeffs + k+1) < (numframeblocks*numcoeffs*2) ? fout[numframeblocks*numcoeffs + l*numcoeffs + k+1] : 0;
                                                                                        double c_1 = (numframeblocks*numcoeffs + l*numcoeffs + k-1) >= numframeblocks*numcoeffs ? fout[numframeblocks*numcoeffs+ l*numcoeffs + k-1] : 0;
                                                                                        double c2 = (numframeblocks*numcoeffs + l*numcoeffs + k+2) < (numframeblocks*numcoeffs*2) ? fout[numframeblocks*numcoeffs + l*numcoeffs + k+2] : 0;
                                                                                        double c_2 = (numframeblocks*numcoeffs + l*numcoeffs + k-2) >= numframeblocks*numcoeffs ? fout[numframeblocks*numcoeffs + l*numcoeffs + k-2] : 0;
                                                                                        
                                                                                        fout[numframeblocks*numcoeffs*2 + l*numcoeffs + k] = ( (c1-c_1) + 2*(c2-c_2) ) / 10 ; 
                                                                                }
                                                                        }
                                                                        
                                                                        for ( int k = 0; k < numcoeffs; k++ ) {
                                                                              for ( int l = 0; l < numframeblocks; l++ ) {
                                                                                        double c1  = (begin + l*numcoeffs + k+1*numcoeffs) < (begin*2) ? fout[begin + l*numcoeffs + k+1*numcoeffs] : fout[begin+ (numframeblocks-1)*numcoeffs + k];
                                                                                        double c_1 = (begin + l*numcoeffs + k-1*numcoeffs) >= begin    ? fout[begin+ l*numcoeffs + k-1*numcoeffs]    : fout[begin+k];
                                                                                        double c2  = (begin + l*numcoeffs + k+2*numcoeffs) < (begin*2) ? fout[begin + l*numcoeffs + k+2*numcoeffs]   : fout[begin+ (numframeblocks-1)*numcoeffs + k];;
                                                                                        double c_2 = (begin + l*numcoeffs + k-2*numcoeffs) >= begin    ? fout[begin + l*numcoeffs + k-2*numcoeffs]   : fout[begin+k];
                                                                                        
                                                                                        fout[numframeblocks*numcoeffs*2 + l*numcoeffs + k] = ( (c1-c_1) + 2*(c2-c_2) ) / 10 ; 
                                                                                }
                                                                        }*/
                                                                        
                                                                        // calculate delta mfccs
                                    int top = numframeblocks*numcoeffs;
                                    for(int k = 0; k < numcoeffs; k++)
                                        calcDelta(fout, 0, top, numcoeffs, top + k * numframeblocks);

                                    //calculate double delta mfccs
                                    for(int k = 0; k < numcoeffs; k++){
                                        int start = top + numframeblocks*k; 
                                        int end =  start + numframeblocks;
                                        calcDelta(fout, start, end, 1, top*2 + k*numframeblocks);
                                    }







                                                                        // calculate energy
                                                                        for ( int l = 0; l < numframeblocks; l++ ) {
                                                                                for ( int j = 0; j < frameblocksize; j++ ) {
                                                                                        double x = Math.pow(wordbufarray[(frameblocksize/frameadvance)*l + j],2)* (0.54-0.46*Math.cos((2*Math.PI*j)/(frameblocksize-1)));
                                                                                        fout[numframeblocks*numcoeffs*3 + l] += x;
                                                                                }
                                                                        }

                                    
                                    //calculate energy deltas
                                    calcDelta( fout, numcoeffs*numframeblocks*3, (numcoeffs*3+1)*numframeblocks, 1, (numcoeffs*3+1)*numframeblocks );
                                    
                                    //calculate energy double deltas
                                    calcDelta( fout, (numcoeffs*3+1)*numframeblocks, (numcoeffs*3+2)*numframeblocks, 1, (numcoeffs*3+2)*numframeblocks);                                     
                                    /**
                                    //reindexing positions to fill fout with energy deltas
                                    int start = numcoeffs * numframeblocks * 3;
                                    int end   = start + numframeblocks;

                                    for( int l = start; l< end; l++)
                                    {
                                        double c1  = l+1  < end   ? fout[l+1] : fout[end-1]; 
                                        double c_1 = l-1  > start ? fout[l-1] : fout[start];
                                        double c2  = l+2  < end   ? fout[l+2] : fout[end-1];
                                        double c_2 = l-2  > start ? fout[l-2] : fout[start];
                                        fout[l+numframeblocks] =  ( (c1-c_1) + 2*(c2-c_2) ) / 10 ; 
                                    }


                                    //do the same for the double energy deltas
                                    start += numframeblocks;
                                    end   += numframeblocks;

                                    for( int l = start; l< end; l++)
                                    {
                                        double c1  = l+1  < end   ? fout[l+1] : fout[end-1]; 
                                        double c_1 = l-1  > start ? fout[l-1] : fout[start];
                                        double c2  = l+2  < end   ? fout[l+2] : fout[end-1];
                                        double c_2 = l-2  > start ? fout[l-2] : fout[start];
                                        fout[l+numframeblocks] =  ( (c1-c_1) + 2*(c2-c_2) ) / 10 ; 
                                    }
                                    **/
                                                                                        
                                                                        
                                                                        /** spectrogram
                                                                        // framing with frameblocksize of 256 
                                                                        int frameblocksize = 64;
                                                                        //int numframeblocks = 2*wordbufarray.length/frameblocksize - 1;
                                                                        int numframeblocks = 253;
                                                                        int numfbins = frameblocksize/2;
                                                                        //int frameadvance = 2;
                                                                        int frameadvance = 4; // advance factor = 1/frameadvance
                                                                        int numcoeffs = 12;

                                                                        double[] fout = new double[numframeblocks*32];
                                                                        for(int l = 0; l < numframeblocks; l++)
                                                                        {
                                                                                double[] frameblock = new double[frameblocksize];
                                                                                for ( int j = 0; j < frameblocksize; j++ ) {
                                                                                        frameblock[j] = wordbufarray[(frameblocksize/4)*l + j] * (0.54-0.46*Math.cos((2*Math.PI*j)/(frameblocksize-1)));
                                                                                }
                                                                                // frameblock now contains a windowed frame of signal
                                                                                Complex[] fftbuf = (new FastFourierTransformer()).transform(frameblock);
                                                                                double[] powspect = new double[fftbuf.length/2];
                                                                                for (int j = 0; j < fftbuf.length/2; j++) 
                                                                                {
                                                                                        powspect[j] = fftbuf[j].multiply( fftbuf[j].conjugate() ).getReal();
                                                                                        fout[l*32 + j] = fftbuf[j].multiply( fftbuf[j].conjugate() ).getReal();
                                                                                }
                                                                        }
                                                                        */
                                                                        
                                                                        // waiting for word to be recieved by driver program
                                                                        while( INVISIBLE && currWordVector != null);

                                                                        // writing features out to file 
                                                                        currWordVector = fout;        
                                                                        out.write( speakerName + "_" + speakerWord );
                                                                        for(int k = 0; k < fout.length; k++)     
                                                                                out.write(" "+ fout[k] );
                                                                        out.write( "\n" );

                                                                        wordbuf.clear();
                                                                }
                                                                else{
                                                                        for(int k = i*framesize; k < (i+1)*framesize; k++)
                                                                                wordbuf.add(inbuf[k]);  
                                                                }
                                                        }
                                                        else {
                                                                silence = 0;
                                                                for(int k = i*framesize; k < (i+1)*framesize; k++)
                                                                        wordbuf.add(inbuf[i]);  
                                                                //System.out.println(i);
                                                        }
                                        }
                                }
                                out.close();
                                //out2.close();
                                //out3.close();
                        }catch (Exception e) {
                                e.printStackTrace();
                                System.exit(0);
                        }

                }//end run
                
        }

        class PlayThread extends Thread{
                byte tempBuffer[] = new byte[10000];

                public void run(){
                        try{
                                int cnt;
                                //Keep looping until the input read method returns -1 for empty stream.
                                while((cnt = audioInputStream.read(tempBuffer, 0, tempBuffer.length)) != -1){
                                        if(cnt > 0){
                                                sourceDataLine.write(tempBuffer, 0, cnt);
                                        }//end if
                                }//end while
                                //Block and wait for internal buffer of the data line to empty.
                                sourceDataLine.drain();
                                sourceDataLine.close();
                        }catch (Exception e) {
                                e.printStackTrace();
                                System.exit(0);
                        }//end catch
                }//end run
        }//end inner class PlayThread
        //===================================//


        private class ButtonListener implements ActionListener
        {
                public void actionPerformed(ActionEvent evt)
                {
                        String arg = evt.getActionCommand();
                        if( arg.equals( ConstVars.ALEX) || arg.equals(ConstVars.KEVIN) || arg.equals(ConstVars.AARON) || arg.equals(ConstVars.MICHAEL) || arg.equals(ConstVars.OTHER) )
                                speakerName = arg;
                        else
                                speakerWord = arg;
                }
        }

}//end outer class AudioCapture01.java

